//重写(override)【一般发生于子类，子类继承父类中已有的方法】
//注意事项：
//1.被private修饰的方法，不能进行重写，一个类的私有
//2.被static修饰的方法，不能进行重写，属于类整体的，并不属于类中的某个成员属性和行为
//3.被final修饰的方法，不能进行重写，final修饰的就是不可变的，
//并且final修饰的类也是不能继承被称之为密封类，所以这种操作也叫做密封方法
//4.访问修饰限定符：子类的被修饰的权限要大于等于父类的权限
//private < 默认 < protected < public
//5.方法的返回值之间可以不同，但是必须是父子类的关系，当然有的书上叫做【协变类型】
//6.构造方法不能发生重写
//7.我们可以用@Override来进行注释，并且他还可以为我们提供一些合法性的检验，比如我们方法名重写错误，那么它就会变红
import com.oracle.jrockit.jfr.UseConstantPool;

class Animals{
    public String name;
    public int age;

    public Animals(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public/*private*/ /*static*/ /*final*/ void eat(){
        System.out.println(this.name + "正在吃饭");
    }

    public Animals lie(){//这部分也构成了方法的重写，但是我用的是类类型
        System.out.println(this.name + "正在平躺");
        return null;
    }
    @Override
    public String toString() {
        return "Animals{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}
class Dog extends Animals{
    public Dog(String name, int age) {
        super(name, age);
    }

    public void wangWang(){
        System.out.println(this.name + "正在狂吠了");
    }
    public void eat(){
        System.out.println(this.name + "正在吃狗粮！！！");
    }
    @Override
    public Dog lie(){
        System.out.println(this.name + "正在趴着");
        return null;
    }//这部分也构成了方法的重写，但是我用的是类类型，所以它是一个引用类型。那么它的返回值就是null，没有指向的地址。

    /*
    但是我们发现了lie这个方法名一样，但是两者的接收的返回值不一样，一个是Animals，一个是Dog，
    两者虽然不一样，但是我们需要明白，dog和Animals两者是父子关系
     */
}

class Birds extends Animals{
    public Birds(String name, int age) {
        super(name, age);
    }
    public void fly(){
        System.out.println(this.name + "正在飞");
    }
}

public class TestDemo {
    public static void main(String[] args) {
        /*
        Animals animals = new Birds("小鸟",10);
        //animals.fly();//向上转型：我们需要明白的是这时候父类引用了子类的对象，它只能调用子类继承父类的方法
        //不能调用子类的特有的方法。
        //说白了飞不起来，那么我们就强迫要他飞起来

        Birds birds = (Birds) animals;
        birds.fly();
        //上述操作这么做就是不安全，这种操作把父类类型给子类类型，这种操作就是被称之为向下转型
        //上述这么做原来的父类引用的是子类bird的对象，但是如果我要引用dog类呢，再强转给birds类呢
        */
        /*
        Animals animals = new Dog("小狗",10);
        Birds birds = (Birds) animals;
        birds.fly();
        //这时候就会报错：ClassCastException(类型转换错误),Dog cannot be cast to Birds
        //因为这个时候我引用的是狗类，所以从狗类转鸟类这个时候就会报错
        //所以我们要用关键字instanceof来检查是否引用了的类与强转为的类是否一致
        */
        Animals animals = new Dog("小狗",10);
        if(animals instanceof Birds) {
            Birds birds = (Birds) animals;
            birds.fly();
        }else{
            System.out.println("不能飞");
        }
        //这么做会较为安全一些
        //instanceof返回值是boolean类型，true和false

    }

    public static void main1(String[] args) {
        Animals animals = new Dog("小狗",10);
        //animals.eat();
        animals.lie();
    }

    //重写的原则：
    //对于已经投入使用的类，尽量不要进行修改。最好的方式是：重新定义一个新的类，来重复利用其中共性的内容，
    //并且添加或者改动新的内容。

    //比如原来的手机只能显示电话号码，现在还有人用，
    //但是现在的新的手机不仅显示电话号码，还能显示地区，显示姓名，那么我们对于这种情况用手机类，对于一个来电显示的方法进行重写

    //向下转型

}
